<gm:page title="My App" authenticate="true" onload="init()">
  
  <style>
    #playBoard tr {
      height: 50px;
    }
    #playBoard td {
      color: blue;
      font-size: 24pt;
      font-weight: bold;
      padding: 5px 0 0 0;
      text-align: center;
      width: 50px;
    }
    .midCell {
      border-left: 1px solid #99B3E6;
      border-right: 1px solid #99B3E6;
    }
  </style>
    
  <script>
    var xoArr = ['O', 'X'];
    var playBoardCellIds = ['OneOne', 'OneTwo', 'OneThree', 'TwoOne', 'TwoTwo', 'TwoThree', 'ThreeOne', 'ThreeTwo', 'ThreeThree'];
    
    var playBoard;
    var emailList;
    var playBoardList;
    var availableGamesList;
    var unavailableGamesList;
    var opposingPlayBoardList;
    
    var playCounterGPath;
    var gameCompletedGPath;
    
    var playerChar = '';
    var opposingPlayerEmail;
    
    function init() {
      playBoard = document.getElementById('playBoard');
      emailList = google.mashups.getObjectById('emailList');
      playBoardList = google.mashups.getObjectById('playBoardList');
      availableGamesList = google.mashups.getObjectById('availableGamesList');
      unavailableGamesList = google.mashups.getObjectById('unavailableGamesList');
      opposingPlayBoardList = google.mashups.getObjectById('opposingPlayBoardList');
      
      gameCompletedGPath = new GPath('gmd:gameCompleted');
      playCounterGPath = new GPath('gmd:playCounter');
      
      var playBoardCells = playBoard.getElementsByTagName('td');
      for (var i=0; i<playBoardCells.length; i++) {
        playBoardCells[i].onclick = playBoardClickHandler;
        playBoardCells[i].innerHTML = '';
      }
    }
    function emailListRepaintHandler() {
      var emailListData = emailList.getData();
    
      if (emailListData.size() == 0) {
        var newEntry = emailListData.createEntry();
        emailListData.addEntry(newEntry);
      }
    }
    function addNewAvailableGame() {
      var emailAddress = new GPath('atom:title').getValue(emailList.getData().entryAt(0));
      var availableGamesListData = availableGamesList.getData();
      
      var emailValidityCheck = checkEmailValidity(emailAddress, true);
      
      if (emailValidityCheck != true) {
        alert(emailValidityCheck);
      }
      else {
        setListVisibility(emailList, false);
    
        var newEntry = availableGamesListData.createEntry();
        new GPath('gmd:player1').setValue(newEntry, emailAddress);
        availableGamesListData.addEntry(newEntry);
        setTimeout('playerOneSubmitHandler()', 5000);
      }
    }
    function startNewGame(DOMElement) {
      var entry = google.mashups.getEntryForElement(DOMElement);
      
      var emailAddress = new GPath('atom:title').getValue(emailList.getData().entryAt(0));
      var unavailableGamesListData = unavailableGamesList.getData();
      var availableGamesListData = availableGamesList.getData();
      
      var emailValidityCheck = checkEmailValidity(emailAddress, false);
      
      if (emailValidityCheck != true) {
        alert(emailValidityCheck);
      }
      else {
        if (new GPath('gmd:player1').getValue(entry) == emailAddress) {
          alert('You cannot play against yourself! Nice try though.');
        }
        else {
          document.getElementById('playBoardControls').style.display = 'block';
          
          playerChar = 'O';          
          opposingPlayerEmail = new GPath('gmd:player1').getValue(entry);
          opposingPlayBoardList.setData('${user}:(' + opposingPlayerEmail + ')/playBoard');
          setOpposingPlayBoardListPeriodicRefresh();
          
          new GPath('gmd:player2').setValue(entry, emailAddress);
          availableGamesList.getData().removeEntry(entry);
          unavailableGamesList.getData().addEntry(entry);
        }
      }
    }
    function checkEmailValidity(emailAddress, checkForDuplicates) {
      if (emailAddress == null) {
        return 'Please enter a valid email address.';
      }
      if (!emailAddress.match(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/)) {
        return 'Email address is not in correct form; please re-enter.';
      }
      
      var emailAccount = emailAddress.replace(/@.*$/, '');
      if (emailAccount != google.mashups.properties['username']) {
        return 'Email account name is not consistent with signed-in username; please re-enter.';
      }
    
      if (checkForDuplicates) {
        var presentFlag = false;
        for (var i=0; i<availableGamesList.getData().size(); i++) {
          var entryEmail = new GPath('gmd:player1').getValue(availableGamesList.getData().entryAt(i));
          if (emailAddress == entryEmail) {
            presentFlag = true;
            break;
          }
        }
        if (presentFlag) {
          return 'You have already added a game; please be patient.';
        }
      }
      
      return true;
    }
    function playerOneSubmitHandler() {
      var gameEntry = null;
      var emailAddress = new GPath('atom:title').getValue(emailList.getData().entryAt(0));
    
      for (var i=0; i<unavailableGamesList.getData().size(); i++) {
        var unavailableGameEntry = unavailableGamesList.getData().entryAt(i);
        if (new GPath('gmd:player1').getValue(unavailableGameEntry) == emailAddress) {
          gameEntry = unavailableGameEntry
          break;
        }
      }
      
      if (gameEntry) {
        document.getElementById('playBoardControls').style.display = 'block';
        
        playerChar = 'X';
        opposingPlayerEmail = new GPath('gmd:player2').getValue(gameEntry);
        opposingPlayBoardList.setData('${user}:(' + opposingPlayerEmail + ')/playBoard');
        setOpposingPlayBoardListPeriodicRefresh();
      }
      else {
        setTimeout('playerOneSubmitHandler()', 5000);
      }
    }
    function playBoardListRepaintHandler() {
      var playBoardListData = playBoardList.getData();

      if (playBoardListData.size() == 0) {
        var newEntry = playBoardListData.createEntry();
        gameCompletedGPath.setValue(newEntry, 'false');
        playCounterGPath.setValue(newEntry, '0');
        playBoardListData.addEntry(newEntry);
      }
      else {
        var gameEntry = playBoardListData.entryAt(0);
        var playCounterStr = playCounterGPath.getValue(gameEntry);
        var playCounter = (+playCounterStr);
        
        for (var i=0; i<playBoardCellIds.length; i++) {
          var cellElement = 'gmd:' + playBoardCellIds[i];
          var cellElementValue = new GPath(cellElement).getValue(gameEntry);
          
          if (cellElementValue!=null) {
            document.getElementById(playBoardCellIds[i]).innerHTML = cellElementValue;
          }
          else {
            document.getElementById(playBoardCellIds[i]).innerHTML = '';
          }
        }
        
        if (playCounter >= 5) {
          checkIfGameCompleted();
        }
      }
    }
    function setOpposingPlayBoardListPeriodicRefresh() {
      var playBoardListData = playBoardList.getData();
      var playBoard = playBoardListData.entryAt(0);
      
      opposingPlayBoardList.refresh();
      var opposingPlayBoardListData = opposingPlayBoardList.getData();
      /*var opposingPlayBoard = opposingPlayBoardListData.entryAt(0);
      
      for (var i=0; i<playBoardCellIds.length; i++) {
        var cellElement = 'gmd:' + playBoardCellIds[i];
        var opposingCellElementValue = new GPath(cellElement).getValue(opposingPlayBoard);
        new GPath(cellElement).setValue(playBoard, opposingCellElementValue);
      }
      playBoardListData.updateEntry(playBoard);*/
      alert(opposingPlayBoardListData.size());
      setTimeout('setOpposingPlayBoardListPeriodicRefresh()', 5000);
    }
    function playBoardClickHandler() {
      var playBoardListData = playBoardList.getData();
      var gameEntry = playBoardListData.entryAt(0);
      
      var gameCompleted = gameCompletedGPath.getValue(gameEntry);
      var playCounter = (+playCounterGPath.getValue(gameEntry));
      
      if (gameCompleted!='true' && isTurn() && this.innerHTML=='') {
        var cellElement = 'gmd:' + this.id;
        playCounter += 1;
        
        playCounterGPath.setValue(gameEntry, String(playCounter));
        new GPath(cellElement).setValue(gameEntry, xoArr[playCounter%2]);
        playBoardListData.updateEntry(gameEntry);
      }
    }
    function isTurn() {
      var opposingPlayBoardListData = opposingPlayBoardList.getData();
      var opposingPlayBoard = opposingPlayBoardListData.entryAt(0);
      
      var opposingPlayCounter = (+playCounterGPath.getValue(opposingPlayBoard));
      
      if (xoArr[(opposingPlayCounter+1)%2] == playerChar) {
        return true;
      }
      else {
        return false;
      }
    }
    function checkIfGameCompleted() {
      var playBoardListData = playBoardList.getData();
      var gameEntry = playBoardListData.entryAt(0);
      
      var playCounter = (+playCounterGPath.getValue(gameEntry));
      var gameComplete = 'false'
      var gameWinner = '';
    
      for (var i=0; i<playBoardCellIds.length; i++) {
        eval('var '+playBoardCellIds[i]+' = new GPath("gmd:'+playBoardCellIds[i]+'").getValue(gameEntry);');
      }
    
      if (OneOne==OneTwo && OneOne==OneThree && OneOne!=null) {
        gameComplete = 'true';
        gameWinner = OneOne;
      }
      else if (TwoOne==TwoTwo && TwoOne==TwoThree && TwoOne!=null) {
        gameComplete = 'true';
        gameWinner = TwoOne;
      }
      else if (ThreeOne==ThreeTwo && ThreeOne==ThreeThree && ThreeOne!=null) {
        gameComplete = 'true';
        gameWinner = ThreeOne;
      }
      else if (OneOne==TwoOne && OneOne==ThreeOne && OneOne!=null) {
        gameComplete = 'true';
        gameWinner = OneOne;
      }
      else if (OneTwo==TwoTwo && OneTwo==ThreeTwo && OneTwo!=null) {
        gameComplete = 'true';
        gameWinner = OneTwo;
      }
      else if (OneThree==TwoThree && OneThree==ThreeThree && OneThree!=null) {
        gameComplete = 'true';
        gameWinner = OneThree;
      }
      else if (OneOne==TwoTwo && OneOne==ThreeThree && TwoTwo!=null) {
        gameComplete = 'true';
        gameWinner = TwoTwo;
      }
      else if (ThreeOne==TwoTwo && ThreeOne==OneThree && TwoTwo!=null) {
        gameComplete = 'true';
        gameWinner = TwoTwo;
      }
      else if (playCounter >= 9) {
        gameComplete = 'true';
        gameWinner = 'NONE';
      }
    
      if (gameComplete == 'true') {
        setTimeout("updateGameStatus('true', '"+gameWinner+"')", 500);
      }
    }
    function updateGameStatus(status, gameWinner) {
      var playBoardListData = playBoardList.getData();
      var gameEntry = playBoardListData.entryAt(0);
      
      gameCompletedGPath.setValue(gameEntry, status);
      new GPath('gmd:gameWinner').setValue(gameEntry, gameWinner);
      playBoardListData.updateEntry(gameEntry);
    }
    function clearPlayBoard() {
      var playBoardListData = playBoardList.getData();
      var gameEntry = playBoardListData.entryAt(0);
    
      if (gameCompletedGPath.getValue(gameEntry) == 'false') {
        alert('Please finish the current game first.');
      }
      else {
        playBoardListData.removeEntry(gameEntry);
      }
    }
    function debugClearPlayBoard() {
      setListVisibility(emailList, true);
      
      var playBoardListData = playBoardList.getData();
      var gameEntry = playBoardListData.entryAt(0);
    
      playBoardListData.removeEntry(gameEntry);
    
      for (var i=0; i<availableGamesList.getData().size(); i++) {
        var availableGameEntry = availableGamesList.getData().entryAt(i);
        availableGamesList.getData().removeEntry(availableGameEntry);
      }
      for (var j=0; j<unavailableGamesList.getData().size(); j++) {
        var unavailableGameEntry = unavailableGamesList.getData().entryAt(j);
        unavailableGamesList.getData().removeEntry(unavailableGameEntry);
      }
    }
    function setListVisibility(list, visible) {
      list.setVisible(visible);
    }
  </script>

  <gm:list id="playBoardList" data="${user}/playBoard" template="debugTemplate">
    <gm:handleEvent event="repaint" execute="playBoardListRepaintHandler()"/>
  </gm:list>
  
  <gm:list id="opposingPlayBoardList" template="debugTemplate"/>
  
  <gm:list id="emailList" data="${user}/email" pagesize="1" selection="false" template="emailListTemplate">
    <gm:handleEvent event="repaint" execute="emailListRepaintHandler()"/>
  </gm:list>
  
  <p>
    <gm:list id="availableGamesList" data="${app}/availableGames" selection="false" template="availableGamesListTemplate"/>
  </p>
  
  <p>
    <gm:list id="unavailableGamesList" data="${app}/unavailableGames" selection="false" template="unavailableGamesListTemplate"/>
  </p>
  
  <div id="playBoardControls" style="display:none">
  <p>
    <table id="playBoard" class="blue-theme">
      <tr>
        <td id="OneOne" class="gm-item-odd"/>
        <td id="OneTwo" class="midCell"/>
        <td id="OneThree" class="gm-item-odd"/>
      </tr>
      <tr>
        <td id="TwoOne"/>
        <td id="TwoTwo" class="gm-item-odd midCell"/>
        <td id="TwoThree"/>
      </tr>
      <tr>
        <td id="ThreeOne" class="gm-item-odd"/>
        <td id="ThreeTwo" class="midCell"/>
        <td id="ThreeThree" class="gm-item-odd"/>
      </tr>
    </table>
  </p>
  
  <p>
    <gm:list data="${user}/test" pagesize="1" template="playBoardInfoListTemplate"/>
  </p>
  </div>
  
  <button onclick="debugClearPlayBoard()">DEBUG New game</button>
  
  <gm:template id="availableGamesListTemplate">
    <table class="blue-theme">
      <thead>
        <tr>
          <th>Player 1</th>
          <th>*</th>
        </tr>
      </thead>
      <tr repeat="true">
        <td><gm:text ref="gmd:player1"/></td>
        <td><button onclick="startNewGame(this)">Play!</button></td>
      </tr>
      <tfoot>
        <tr>
          <td colspan="2"><button onclick="addNewAvailableGame()">Add</button></td>
        </tr>
      </tfoot>
    </table>
  </gm:template>
  
  <gm:template id="unavailableGamesListTemplate">
    <table class="blue-theme">
      <thead>
        <tr>
          <th>Player 1</th>
          <th>Player 2</th>
        </tr>
      </thead>
      <tr repeat="true">
        <td><gm:text ref="gmd:player1"/></td>
        <td><gm:text ref="gmd:player2"/></td>
      </tr>
      <tfoot>
        <tr>
          <td colspan="2"></td>
        </tr>
      </tfoot>
    </table>
  </gm:template>
  
  <gm:template id="emailListTemplate">
    <p align="center">
    <h5 style="margin:0px">Enter email:</h5>
    <div repeat="true">
      <gm:text ref="atom:title"/>
      <gm:editButtons editonly="true" text="true"/>
    </div>
    </p>
  </gm:template>  
  
  <gm:template id="debugTemplate">
    <div repeat="true">
    
    <table border="1">
      <tr><th colspan="3"><gm:text ref="gmd:complete"/>&nbsp;<gm:text ref="gmd:playCtr"/></th></tr>
    <tr style="height:50px">
      <td style="width:50px"><gm:text ref="gmd:OneOne"/></td>
      <td style="width:50px"><gm:text ref="gmd:OneTwo"/></td>
      <td style="width:50px"><gm:text ref="gmd:OneThree"/></td>
    </tr>
    <tr style="height:50px">
      <td><gm:text ref="gmd:TwoOne"/></td>
      <td><gm:text ref="gmd:TwoTwo"/></td>
      <td><gm:text ref="gmd:TwoThree"/></td>
    </tr>
    <tr style="height:50px">
      <td><gm:text ref="gmd:ThreeOne"/></td>
      <td><gm:text ref="gmd:ThreeTwo"/></td>
      <td><gm:text ref="gmd:ThreeThree"/></td>
    </tr>
  </table>
  </div>
  </gm:template>
  
  <gm:template id="playBoardInfoListTemplate">
    <div repeat="true">
      <b>Complete:</b>&nbsp;<gm:text ref="gmd:gameCompleted"/>
      <br/>
      <b>Winner:</b>&nbsp;<gm:text ref="gmd:gameWinner"/>
    </div>
  </gm:template>
    
</gm:page>